#include "CWorldEngine.h"

CWorldEngine::CWorldEngine()
{
	m_pTM = CSGD_TextureManager::GetInstance();
	map = NULL;
}

CWorldEngine::~CWorldEngine()
{
	UnLoadMap();
}

CWorldEngine* CWorldEngine::GetInstance()
{
	static CWorldEngine instance;
	return &instance;
}

void CWorldEngine::LoadMap(char* filename)
{
	UnLoadMap();

	ifstream reader;
	reader.open(filename, ios::in | ios::binary);
	//map->tileMapID = m_pTM->LoadTexture("Resources/graphics/_default.jpg");
	
	if(reader.is_open())
	{
		map = new Map();
		map->Clear();

		char buff[25];
		int fileNameLength;
		reader.read((char*)&fileNameLength, sizeof(int));
		reader.read(buff, fileNameLength);
		buff[fileNameLength] = 0;

		char filePath[50] = "Resources\\graphics\\";
		strcat_s(filePath, 50, buff);

		map->tileMapID = m_pTM->LoadTexture(filePath);

		reader.read((char*)&map->mapWidth, sizeof(int));
		reader.read((char*)&map->mapHeight, sizeof(int));
		reader.read((char*)&map->tileWidth, sizeof(int));
		reader.read((char*)&map->tileHeight, sizeof(int));
		reader.read((char*)&map->tileSetWidth, sizeof(int));
		reader.read((char*)&map->tileSetHeight, sizeof(int));

		for(int layer = 0; layer < 3; ++layer)
		{
			Layer* tempLayer = new Layer();
			char buff[25];
			int layerNameLength;

			reader.read((char*)&layerNameLength, sizeof(int));	
			reader.read(buff, layerNameLength);		
			buff[layerNameLength] = 0;
			tempLayer->layerName = buff;

			tempLayer->tileMap = new Tile*[map->mapWidth];
			for(int i = 0; i < map->mapWidth; ++i)
				tempLayer->tileMap[i] = new Tile[map->mapHeight];

			for(int i = 0; i < map->mapWidth; ++i)
			{
				for(int j = 0; j < map->mapHeight; ++j)
				{
					reader.read((char*)&tempLayer->tileMap[i][j].tileIndex, sizeof(int));
					reader.read((char*)&tempLayer->tileMap[i][j].hasCollision, sizeof(bool));
					if(tempLayer->tileMap[i][j].hasCollision)
					{
						tempLayer->tileMap[i][j].collisionRect.left = i * map->tileWidth;
						tempLayer->tileMap[i][j].collisionRect.right = tempLayer->tileMap[i][j].collisionRect.left + map->tileWidth;
						tempLayer->tileMap[i][j].collisionRect.top = j * map->tileHeight;
						tempLayer->tileMap[i][j].collisionRect.bottom = tempLayer->tileMap[i][j].collisionRect.top + map->tileHeight;
						
						reader.read((char*)&tempLayer->tileMap[i][j].collisionType, sizeof(int));
						reader.read((char*)&tempLayer->tileMap[i][j].hasEvent, sizeof(bool));
						if(tempLayer->tileMap[i][j].hasEvent)
						{
							char buff[25];
							int eventLength;
							reader.read((char*)&eventLength, sizeof(int));
							reader.read(buff, eventLength);
							buff[eventLength] = 0;
							tempLayer->tileMap[i][j].collisionEvent = buff;
						}
					}
					else
					{
						tempLayer->tileMap[i][j].collisionType = 0;
					}
					reader.read((char*)&tempLayer->tileMap[i][j].hasObject, sizeof(bool));
					if(tempLayer->tileMap[i][j].hasObject)
					{
						reader.read((char*)&tempLayer->tileMap[i][j].objectType, sizeof(int));

						char buff[25];
						int objectLength;
						reader.read((char*)&objectLength, sizeof(int));
						reader.read(buff, objectLength);
						buff[objectLength] = 0;
						tempLayer->tileMap[i][j].objectName = buff;

						switch(tempLayer->tileMap[i][j].objectType)
						{
						case ENEMYSPAWN:
							break;
						case SAVEPOINT:
							{
								CSavePoint* save;
								save = (CSavePoint*)ObjectFactory<string,CBase>::GetInstance()->CreateObject("CSavePoint");
								save->SetPosX(i * map->tileWidth);
								save->SetPosY(j * map->tileHeight);
								ObjectManager::GetInstance()->AddObject(save);
								save->Release();
							}
							break;
						}
					}
					else
					{
						tempLayer->tileMap[i][j].objectType = 0;
					}
				}
			}
			tempLayer->visible = true;
			map->layerList.push_back(tempLayer);
		}
		reader.close();
	}
}

void CWorldEngine::UnLoadMap()
{
	if( map != 0 )
	{
		for(int i = 0; i < 3; ++i)
		{
			for(int k = 0; k < map->mapWidth; ++k)
			{
				delete[] map->layerList[i]->tileMap[k];
			}
			delete[] map->layerList[i]->tileMap;
			delete map->layerList[i];
		}
		delete map;
		map = NULL;
	}
}


void CWorldEngine::DrawMap()
{
	for(int layer = 0; layer < 3; ++layer)
	{
		if(map->layerList[layer]->visible)
		{
			for(int i = 0; i < map->mapWidth; ++i)
			{
				for(int j = 0; j < map->mapHeight; ++j)
				{
					if(map->layerList[layer]->tileMap[i][j].tileIndex != -1)
					{
						int drawTile = map->layerList[layer]->tileMap[i][j].tileIndex;
						int moveDown = 0;

						while(drawTile > (map->tileSetWidth -1))
						{
							drawTile -= (map->tileSetWidth);
							++moveDown;
						}
						RECT dRect;
						dRect.left = drawTile * map->tileWidth;
						dRect.right = dRect.left + map->tileWidth;
						dRect.top = moveDown * map->tileHeight;
						dRect.bottom = dRect.top + map->tileHeight;

						if(i * map->tileWidth > (CCamera::GetInstance()->GetCameraPosX() - map->tileWidth) &&
							i * map->tileWidth < (CCamera::GetInstance()->GetCameraPosX() + CGame::GetInstance()->GetScreenWidth() + map->tileWidth) &&
							j * map->tileHeight > (CCamera::GetInstance()->GetCameraPosY() - map->tileHeight) &&
							j * map->tileHeight < (CCamera::GetInstance()->GetCameraPosY() + CGame::GetInstance()->GetScreenHeight() + map->tileHeight))
							m_pTM->Draw(map->tileMapID, (i * map->tileWidth) - CCamera::GetInstance()->GetCameraPosX(), 
								(j * map->tileHeight) - CCamera::GetInstance()->GetCameraPosY(),1.0f, 1.0f, &dRect);
					}
				}
			}
		}
	}
}

int CWorldEngine::CheckCollision(CBase* pBase)
{
	int nSomething = 0;

	for(int layer = 0; layer < 3; ++layer)
	{
		if(map->layerList[layer]->visible)
		{
			for(int i = 0; i < map->mapWidth; ++i)
			{
				for(int j = 0; j < map->mapHeight; ++j)
				{
					if(map->layerList[layer]->tileMap[i][j].tileIndex != -1)
					{
							RECT rect;
							if(IntersectRect(&rect, &pBase->GetCollisionRect(), &map->layerList[layer]->tileMap[i][j].collisionRect))
							{
								if(map->layerList[layer]->tileMap[i][j].collisionType == SOLID)
								{
									if( (rect.bottom - rect.top) > (rect.right - rect.left))
									{
										if(rect.right == pBase->GetCollisionRect().right)
										{
											pBase->SetPosX(pBase->GetPosX() - (rect.right - rect.left));
										}
										else
										{
											pBase->SetPosX(pBase->GetPosX() + (rect.right - rect.left));
										}
										return NONE;
									}
									else
									{
										if(rect.bottom == pBase->GetCollisionRect().bottom)
										{
											pBase->SetPosY( ( pBase->GetPosY() +1 ) - (rect.bottom - rect.top));
										}
										else
										{
											pBase->SetPosY(( pBase->GetPosY() +1 ) + (rect.bottom - rect.top));
										}
									}
								}
								else if(map->layerList[layer]->tileMap[i][j].collisionType == EVENT)
								{
									//SEND EVENT (needs event system)
								}
								nSomething =  map->layerList[layer]->tileMap[i][j].collisionType;
							}
					}
				}
			}
		}
	}

	return nSomething;
}

bool CWorldEngine::CheckSolid(CBase* pBase)
{
	for(int layer = 0; layer < 3; ++layer)
	{
		if(map->layerList[layer]->visible)
		{
			for(int i = 0; i < map->mapWidth; ++i)
			{
				for(int j = 0; j < map->mapHeight; ++j)
				{
					if(map->layerList[layer]->tileMap[i][j].tileIndex != -1)
					{
						RECT rect;
						if(IntersectRect(&rect, &pBase->GetCollisionRect(), &map->layerList[layer]->tileMap[i][j].collisionRect))
						{
							if(map->layerList[layer]->tileMap[i][j].collisionType == SOLID)
							{
								return true;
							}
						}
					}
				}
			}
		}
	}
	return false;
}

void CWorldEngine::Map::Clear()
{
	tileMapID = -1;
	layerList.clear();
	mapWidth = 0;
	mapHeight = 0;
	tileWidth = 0;
	tileHeight = 0;
	tileSetWidth = 0;
	tileSetHeight = 0;
}